package com.algo.aldi;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

@PersistJobDataAfterExecution
public class SimpleJob3 implements InterruptableJob {

    public static void main(String[] args) throws SchedulerException, InterruptedException {

        JobDetail job = newJob(SimpleJob3.class)
                .withIdentity("job1", "group1")

                .build();

        new Thread(() -> {

            try {
                while (true) {

                    Scheduler scheduler = chooseScheduler();
                    if (scheduler == null) {
                        break;
                    }

                    while (true) {
                        Object executed = scheduler.getJobDetail(job.getKey()).getJobDataMap().get("executed");
                        if (executed != null && (boolean) executed) {
                            System.out.println(" ============= current scheduler is finish");
                            scheduler.shutdown();
                            break;
                        }
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println(" *************************** ");
                    }
                    System.out.println(" ############################### ");
                }
            } catch (SchedulerException | InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        TimeUnit.HOURS.sleep(24);
    }

    public static Scheduler builtScheduler(Trigger trigger, JobDetail job) throws SchedulerException {
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        sched.scheduleJob(job, trigger);

        sched.start();
        return sched;
    }

    static Scheduler chooseScheduler() throws SchedulerException {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Date now = new Date();
        String nowStr = sdf.format(now);

        Map.Entry<String, CronTrigger> cronTriggerEntry = triggerMap.higherEntry(nowStr);
        if (cronTriggerEntry == null) {
            System.out.println("gave over ... ");
            return null;
        }
        JobDetail jobDetail = jobMap.get(cronTriggerEntry.getKey());
        return builtScheduler(cronTriggerEntry.getValue(), jobDetail);
    }

    static int TIMES = 2;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            Integer no = (Integer) context.getJobDetail().getJobDataMap().get("no");
            for (int i = 0; i < TIMES; i++) {
                task(no);
//                fake_task();
            }
            context.getJobDetail().getJobDataMap().put("executed", true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void fake_task() {
        System.out.println(" =================== " + System.currentTimeMillis());
    }

    private static void task(int questionNo) {

        executorService.submit(() -> {
            reqs.forEach(v -> {
//                System.out.println(Thread.currentThread() + " - " + new Date() + " === " + JSON.toJSONString(v.get(questionNo)));
                ResponseEntity<String> response = restTemplate.postForEntity(url, v.get(questionNo), String.class);
                System.out.println(response.getBody());
            });


        });
    }

    static ExecutorService executorService = Executors.newFixedThreadPool(4);

    static int count = 3;

    static String[] goodIds = {"38", "39", "41"};
    static String[] answers = {"不可以", "每周二", "门店线下兑换"};

    static String[] uts = {"%40%25%5E%2AMd3InnJdxqMDSu1vVlkS%2FEGjbtUe6NSQL9wrIXl3S6k%3D"};
    static String url = "https://alq2020.69dp.cn/Api/UserSeckill/addOrder";
    static RestTemplate restTemplate = new RestTemplate();

    static List<List<HttpEntity<MultiValueMap<String, String>>>> reqs = new ArrayList<>();

    static {
        for (String ut : uts) {
            List<HttpEntity<MultiValueMap<String, String>>> requests = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                HttpHeaders headers = new HttpHeaders();
                //设置为form方式
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
                map.add("ut", ut);
                map.add("userid", ut);
                map.add("goods_id", goodIds[i]);
                map.add("answer", answers[i]);
                HttpEntity<MultiValueMap<String, String>> requestb = new HttpEntity<>(map, headers);
                requests.add(requestb);
            }
            reqs.add(requests);
        }
    }

    static String[] times = {"10:00", "10:30", "11:00"};
    static String[] crons = {"0 0 10 * * ? *", "0 30 10 * * ? *", "0 0 11 * * ? *"};
//    static String[] times = {"09:44", "09:45", "09:46"};
//    static String[] crons = {"0/10 * * * * ? *", "0/10 * * * * ? *", "0/10 * * * * ? *"};
    static TreeMap<String, CronTrigger> triggerMap = new TreeMap<>();
    static Map<String, JobDetail> jobMap = new HashMap<>();

    static {
        for (int i = 0; i < count; i++) {
            JobDataMap newJobDataMap = new JobDataMap();
            newJobDataMap.put("executed", false);
            newJobDataMap.put("no", i);
            CronTrigger trigger = newTrigger()
                    .withIdentity("trigger1", "group1")
                    .withSchedule(cronSchedule(crons[i]))
                    .build();
            triggerMap.put(times[i], trigger);

            JobDetail job = newJob(SimpleJob3.class)
                    .withIdentity("job1", "group1")
                    .usingJobData(newJobDataMap)
                    .storeDurably()
                    .build();
            jobMap.put(times[i], job);
        }
    }

    // 当前逻辑没用...
    @Override
    public void interrupt() {

    }
}
